package com.naiterui.ehp.bs.pc.common.vo;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.naiterui.ehp.bs.pc.common.utils.DateUtils;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

/**
 * 分页请求参数
 *
 * @author 王泽浩
 * @date 2018/4/15 下午9:18
 * @since 1.0.0
 */
@Slf4j
@Data
public class PageParamsVO implements java.io.Serializable {

  private static final long serialVersionUID = -7371309666517076389L;

  /**
   * 开始时间
   */
  private String dateGte;
  /**
   * 结束时间
   */
  private String dateLte;

  /**
   * 当前页码
   */
  private Integer pageNo;
  /**
   * 每页条数
   */
  private Integer pageSize;

  /**
   * 排序 asc desc
   */
  private String orderBy;

  /**
   * 排序字段
   */
  private String orderByField;

  /**
   * mybatis-plus分页对象
   *
   * @return page对象
   */
  @JsonIgnore
  public <T> IPage<T> getPage() {
    Page<T> page = new Page<>(this.pageNo == null ? 1 : this.pageNo, this.pageSize == null ? 10 : this.pageSize);
    // 排序
    if (StringUtils.isNotBlank(this.orderByField) && StringUtils.isNotBlank(this.orderBy)) {
      this.orderByField = this.humpToUnderline(this.orderByField);
      if ("ASC".equalsIgnoreCase(this.orderBy)) {
        page.addOrder(OrderItem.asc(this.orderByField));
      } else {
        page.addOrder(OrderItem.desc(this.orderByField));
      }
    }
    return page;
  }

  private String humpToUnderline(String para) {
    if (this.sqlValidate(para)) {
      log.error("当前请求存在sql注入攻击 请求参数：{}", para);
      throw new IllegalArgumentException("当前请求存在非法字符！");
    }

    StringBuilder sb = new StringBuilder(para);
    int temp = 0;
    for (int i = 0; i < para.length(); i++) {
      if (Character.isUpperCase(para.charAt(i))) {
        sb.insert(i + temp, "_");
        temp += 1;
      }
    }
    return sb.toString().toUpperCase();
  }

  // 效验
  private boolean sqlValidate(String str) {
    if (Lists.newArrayList("orderNum", "createdAt", "order_status").contains(str)) {
      return false;
    }
    // 统一转为小写
    str = str.toLowerCase();
    // 过滤掉的sql关键字，可以手动添加
    String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|"
        + "char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|"
        + "table|from|grant|use|group_concat|column_name|"
        + "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|"
        + "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#";
    String[] badStrs = badStr.split("\\|");
    List<String> collect = Arrays.stream(badStrs).collect(Collectors.toList());
    for (String s : collect) {
      if (str.contains(s)) {
        return true;
      }
    }
    return false;
  }


  /**
   * 获取EntityWrapper
   *
   * @param t
   * @return
   */
  @JsonIgnore
  public <T> QueryWrapper<T> getEntityWrapper(T t) {
    QueryWrapper<T> entityWrapper = new QueryWrapper<>(t);
    entityWrapper.ge(StringUtils.isNotBlank(this.dateGte), "created_at", this.dateGte);
    if (StringUtils.isNotBlank(this.dateLte)) {
      if (DateUtils.isNow(this.dateLte)) {
        Date plus = DateUtils.plus(DateUtils.parseStrToDate(this.dateLte), 1, ChronoUnit.DAYS);
        entityWrapper.le("created_at", plus);
      } else {
        entityWrapper.le("created_at", this.dateLte);
      }
    }
    return entityWrapper;
  }

  @JsonIgnore
  public <T> QueryWrapper<T> getEntityWrapper(String fromTabelAlias) {
    QueryWrapper<T> entityWrapper = new QueryWrapper<>();

    String createdAt = Joiner.on(".").skipNulls().join(fromTabelAlias, "created_at");
    entityWrapper.ge(StringUtils.isNotBlank(this.dateGte), createdAt, this.dateGte);
    if (StringUtils.isNotBlank(this.dateLte)) {
      if (DateUtils.isNow(this.dateLte)) {
        Date plus = DateUtils.plus(DateUtils.parseStrToDate(this.dateLte), 1, ChronoUnit.DAYS);
        entityWrapper.le(createdAt, plus);
      } else {
        entityWrapper.le(createdAt, this.dateLte);
      }
    }

    return entityWrapper;
  }

}
